/*
 * Copyright (C) 2017 Intel Corporation.  All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef __LOGS_H_
#define __LOGS_H_

#include <stdarg.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#define LOG_BUF_SIZE      1024
#define LOG_MASK_SIZE     10

#ifndef LOG_MY_MASK_ID
#define LOG_MY_MASK_ID     0
#endif


#define LOG_PLUGIN_MASK_ID  7


#ifndef LOG_COAP_MASK_ID
#define LOG_COAP_MASK_ID  8
#endif
#ifndef LOG_WAGENT_SDK_MASK_ID
#define LOG_WAGENT_SDK_MASK_ID  9
#endif


typedef uint16_t log_id_t;
#define DEFAULT_LOG_ID (log_id_t)0

enum{
	LOG_VERBOSE = 0,
	LOG_INFO = 1,
	LOG_DEBUG = 2,
	LOG_WARN = 3,
	LOG_ERROR = 4
};

#define LOG_LEVEL_DEFAULT LOG_DEBUG
#define LOG_MASK_DEFAULT 0xFF



extern unsigned long log_tag_mask[LOG_MASK_SIZE];
extern unsigned char log_level;

//
#define FLAG_DEFAULT 0x00000001

#define LOG_SET(flag)  ((log_tag_mask[LOG_MY_MASK_ID]) & (flag))
#define LOGV_SET(flag)  ((log_tag_mask[LOG_MY_MASK_ID]) & (flag) && (LOG_VERBOSE >= log_level))
#define LOGI_SET(flag)  ((log_tag_mask[LOG_MY_MASK_ID]) & (flag) && (LOG_INFO >= log_level))


#define ERROR(...) if((LOG_ERROR   >= log_level)) log_print("E:" LOG_TAG, __VA_ARGS__)
#define WARNING(...) if((LOG_WARN  >= log_level)) log_print("W:" LOG_TAG, __VA_ARGS__)
#define INFO(...) if((LOG_INFO  >= log_level)) log_print(LOG_TAG, __VA_ARGS__)

#define WARNING2(...) if((LOG_WARN  >= log_level)) log_print(__FUNCTION__ , __VA_ARGS__)


#define WALOG(...) log_print(LOG_TAG, __VA_ARGS__)
#define LOG2(...) log_print(__FUNCTION__, __VA_ARGS__)

#define LOGX(...) log_print(LOG_TAG, __VA_ARGS__)


#define Trace(flag, level, tag, ...) if((log_tag_mask[LOG_MY_MASK_ID] & flag) && (LOG_VERBOSE >= level)) log_print(tag, __VA_ARGS__)

#define TraceD(flag,...) if((log_tag_mask[LOG_MY_MASK_ID] & flag) && (LOG_DEBUG   >= log_level)) log_print(__FUNCTION__ , __VA_ARGS__)
#define TraceI(flag,...) if((log_tag_mask[LOG_MY_MASK_ID] & flag) && (LOG_INFO >= log_level)) log_print( LOG_TAG, __VA_ARGS__)
#define TraceV(flag,...) if((log_tag_mask[LOG_MY_MASK_ID] & flag) && (LOG_VERBOSE >= log_level)) log_print("V:" LOG_TAG, __VA_ARGS__)


#define WA_WARN(...) if(LOG_WARN   >= log_level) log_print( __FUNCTION__, __VA_ARGS__)
#define WA_DEBUG(...) if(LOG_DEBUG   >= log_level) log_print(__FUNCTION__, __VA_ARGS__)
#define WA_INFO(flag,...) if((log_tag_mask[LOG_MY_MASK_ID] & flag) && (LOG_INFO >= log_level)) log_print( __FUNCTION__, __VA_ARGS__)
#define WA_VERBOS(flag,...) if((log_tag_mask[LOG_MY_MASK_ID] & flag) && (LOG_VERBOSE >= log_level)) log_print(__FUNCTION__, __VA_ARGS__)

#define WA_LOG(log_mask, flag, level, ...) if((log_mask<LOG_MASK_SIZE) && (log_tag_mask[log_mask] & flag) && (level >= log_level)) log_print(__FUNCTION__, __VA_ARGS__)

#define LOG_DATA(flag,title, buffer, len) if(len >0 && (log_tag_mask[LOG_MY_MASK_ID]  & flag) && (LOG_DEBUG   >= log_level)) log_buffer(title,buffer, len)

#define LOG_MSG(message)  if((LOG_WARN   >= log_level)) log_print("E:" LOG_TAG, "%s, function: %s,line: %d", message, __FUNCTION__, __LINE__);
#define LOG_ME()  if((LOG_WARN   >= log_level)) log_print("E:" LOG_TAG, "error condition in function %s, line %d", __FUNCTION__, __LINE__);
#define LOG_RETURN(ret)  { if(LOG_WARN   >= log_level)  log_print("E:" LOG_TAG, "return for error condition. function: %s, line: %d", __FUNCTION__, __LINE__); return ret;}
#define LOG_GOTO(message, label)  { if(LOG_WARN   >= log_level)  log_print("E:" LOG_TAG, "%s, leave for error condition. function: %s, line: %d",  message, __FUNCTION__, __LINE__); goto label;}


void log_init(const char* app, const char* log_path, const char* log_cfg_path);
void log_setlevel(int level);
void log_set_tag_mask(int tag_slot, int tag_mask);
void log_clear_tag_mask(int tag_slot,int tag_mask);
void log_print(const char* tag, const char* fmt, ...);
void log_print2(log_id_t slot,const char* tag, const char* fmt, va_list ap);
void log_check_refresh(int upload);
void log_gen();
char* log_to();
char * now_str(char *s );
void log_buffer(char * title, void * buffer,   int length);
FILE * log_get_handle();
void do_log(log_id_t idx,const char * buf);
bool log_init_slot(log_id_t slot, const char * log_path , long max_size_KB);
void log_print_slot(log_id_t slot,const char* tag, const char* fmt, ...);


#ifdef __cplusplus
}
#endif

#endif
